package main

import (
	"dfws/dfw"
	"dfws/rsa"
	"flag"
	"fmt"
	"github.com/kardianos/service"
	termbox "github.com/nsf/termbox-go"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
)

var logger service.Logger

var action string
var id string
var host string
var port int
var timeout int
var testUrl string
var testRegex string
var workDir string

func init() {
	flag.StringVar(&action, "action", "client", "交互命令： genKey client clientx server 服务命令： install uninstall start stop restart status")
	flag.StringVar(&id, "id", "test", "请输入秘钥文件名或秘钥")
	flag.StringVar(&host, "host", "localhost", "服务地址")
	flag.IntVar(&port, "port", 6760, "服务端口")
	flag.IntVar(&timeout, "timeout", 0, "超时时间，单位秒")
	flag.StringVar(&testUrl, "url", "", "获取外网IP的服务器地址")
	flag.StringVar(&testRegex, "regex", "", "正则表达式提取")

	if err := termbox.Init(); err != nil {
		panic(err)
	}
	termbox.SetCursor(0, 0)
	termbox.HideCursor()

}

func main() {
	flag.Parse()
	workDir = GetCurrentDirectory() + "/conf"
	if action == "genKey" || action == "genKeyX" {
		log.Println(action, ": ", id)
		rsa.GenerateRSAKey(workDir, 2048, id)
		if action == "genKeyX" {
			pause()
		}
		return
	} else if action == "dns" {
		log.Println(action, ": ", id)
		dfw.SetDnsDfw(workDir, id)
		return
	} else if action == "client" || action == "clientX" {
		log.Println(action, ": ", id, ", host:", host, ", port:", port, ", timeout:", timeout, ", testUrl:", testUrl, ", testRegex:", testRegex)
		dfw.StartClient(workDir, id, host, port, timeout, testUrl, testRegex)
		if action == "clientX" {
			pause()
		}
		return
	} else if action == "server" {
		log.Println(action, ":  host:", host, ", port:", port, ", timeout:", timeout)
		dfw.StartServer(workDir, host, port, timeout)
		return
	} else {
		options := make(service.KeyValue)
		options["LogOutput"] = true
		options["HasOutputFileSupport"] = true
		options["WorkingDirectory"] = workDir

		svcConfig := &service.Config{
			Name:        "dfw",
			DisplayName: "动态IP信任防火墙服务",
			Description: "动态IP信任防火墙服务",
			Option:      options,
			//Arguments :
		}
		svcConfig.Arguments = append(svcConfig.Arguments, "-action")
		svcConfig.Arguments = append(svcConfig.Arguments, "server")
		if host != "" {
			svcConfig.Arguments = append(svcConfig.Arguments, "-host")
			svcConfig.Arguments = append(svcConfig.Arguments, host)
		}
		if port > 0 {
			svcConfig.Arguments = append(svcConfig.Arguments, "-port")
			svcConfig.Arguments = append(svcConfig.Arguments, strconv.Itoa(port))
		}
		if timeout > 0 {
			svcConfig.Arguments = append(svcConfig.Arguments, "-timeout")
			svcConfig.Arguments = append(svcConfig.Arguments, strconv.Itoa(timeout))
		}
		if runtime.GOOS == "windows" {
		} else {
			svcConfig.Dependencies = []string{
				"Requires=network.target",
				"After=network-online.target syslog.target"}
			svcConfig.UserName = "root"
		}
		pro := &Program{}
		s, err := service.New(pro, svcConfig)
		if err != nil {
			log.Fatal("service.New() err:", err)
		}
		errs := make(chan error, 5)
		logger, err = s.Logger(errs)
		if err != nil {
			log.Fatal(err)
		}
		if action == "install" {
			log.Println(action, ":  host:", host, ", port:", port, ", timeout:", timeout)
			err = s.Install()
			if err != nil {
				logger.Error("安装服务成功:", err)
			} else {
				logger.Info("安装服务成功")
			}
			return
		} else if action == "uninstall" {
			log.Println(action)
			err = s.Uninstall()
			if err != nil {
				logger.Error("卸载服务失败:", err)
			} else {
				logger.Info("卸载服务成功")
			}
			return
		} else if action == "stop" {
			log.Println(action)
			err = s.Stop()
			return
		} else if action == "restart" {
			log.Println(action)
			err = s.Restart()
			return
		} else if action == "status" {
			log.Println(action)
			status, err := s.Status()
			logger.Info("status:", status, " （1运行，2停止）")
			if err != nil {
				logger.Error("服务启动失败:", err)
			}
			return
		}
		log.Println(action, ":  host:", host, ", port:", port, ", timeout:", timeout)
		err = s.Run() // 运行服务
		if err != nil {
			logger.Error("服务启动失败:", err)
		}
	}
}

type Program struct {
	exit chan struct{}
}

func (p *Program) Start(s service.Service) error {
	logger.Infof("启动服务 %v. action: %v", service.Platform(), action)
	p.exit = make(chan struct{})
	go p.run()
	return nil
}
func (p *Program) Stop(s service.Service) error {
	logger.Info("停止服务!")
	close(p.exit)
	return nil
}

func (p *Program) run() {
	// 启动服务
	dfw.StartServer(workDir, host, port, timeout)
}
func GetCurrentDirectory() string {
	dir, err := filepath.Abs(filepath.Dir(os.Args[0])) //返回绝对路径  filepath.Dir(os.Args[0])去除最后一个元素的路径
	if err != nil {
		log.Fatal(err)
	}
	return strings.Replace(dir, "\\", "/", -1) //将\替换成/
}

func pause() {
	fmt.Println("请按任意键继续...")
Loop:
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			break Loop
		}
	}
}
